﻿using System.Net;
using System.Transactions;
using GamFi.Admin.API.Application.Exceptions;
using Newtonsoft.Json;

namespace GamFi.Admin.API.WEB.Middlewares;

public class ExceptionHandlingMiddleware(RequestDelegate next)
{
    public async Task Invoke(HttpContext context)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        HttpStatusCode statusCode;
        string errorMessage;

        switch (exception)
        {
            case UserException userException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = userException.Message;
                break;

            case ImageException imageException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = imageException.Message;
                break;

            case WalletException walletException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = walletException.Message;
                break;

            case ChatException chatException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = chatException.Message;
                break;

            case HttpContextException httpContextException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = httpContextException.Message;
                break;
            
            case ChainException chainException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = chainException.Message;
                break;
            
            case TransactionException transactionException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = transactionException.Message;
                break;

            case RequestException requestException:
                statusCode = HttpStatusCode.BadRequest;
                errorMessage = requestException.Message;
                break;

            default:
                statusCode = HttpStatusCode.InternalServerError;
                errorMessage = "An unexpected error occurred.";
                break;
        }

        LogException(context, exception, statusCode, errorMessage);

        var result = JsonConvert.SerializeObject(new { error = errorMessage });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)statusCode;
        return context.Response.WriteAsync(result);
    }

    private static void LogException(HttpContext context, Exception exception, HttpStatusCode statusCode,
        string errorMessage)
    {
        var logMessage = $"""
                              Exception: {exception.GetType().Name}
                              Message: {exception.Message}
                              Status Code: {(int)statusCode} ({statusCode})
                              Path: {context.Request.Path}
                              Method: {context.Request.Method}
                              Query: {context.Request.QueryString}
                              Stack Trace:
                          {exception.StackTrace}
                              
                          """;

        Console.Error.WriteLine(logMessage);
    }
}